package com.open.ui.skin;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.collection.SimpleArrayMap;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;

import com.open.ui.R;
import com.open.ui.widget.TVUIButton;
import com.open.ui.widget.TVUICommonItemView;
import com.open.ui.widget.TVUITextView;

/**
 * <pre>
 * 1.加载本地的 style.
 * 2.添加(addSkin)到主题管理器(SkinManager)
 *   skinManager.addSkin(SKIN_BLUE, R.style.app_skin_blue);
 *   skinManager.addSkin(SKIN_DARK, R.style.app_skin_dark);
 *   skinManager.addSkin(SKIN_WHITE, R.style.app_skin_white);
 * 3.改变主题 changeSkin
 *
 * // 拿到控件View的 attr，放入. 现在是手动，如何自动？？？值得思考
 * // 1. SimpleArrayMap<String, Integer> skinAttrs;
 * // 2. 背景相关的关键字.
 * //    skinAttrs.put("background", R.attr.tvui_main_layout_background); 比如主布局的
 * //    skinAttrs.put("background", R.attr.tvui_backgroundColor); // 比如 TvUIButton
 * // 3. for (int i = 0; i < skinAttrs.size(); i++)
 * // 4. 获取 attr 去获取对应的资源，根据 background 标识，判断对应的View写入背景.
 * //    比如 TVUILayout.setBackground...
 * </pre>
 */
public class SkinManager {

    public static final String BACKGROUND_TAG = "background"; // 背景
    public static final String IMAGE_TINT_TAG = "imageTintColor"; // 右侧图标颜色
    public static final String ARROW_TINT_TAG = "arrowTintColor"; // 左侧图标颜色
    public static final String TEXT_COLOR_TAG = "textColor"; // 文本颜色
    public static final String SECOND_TEXT_COLOR_TAG = "secondTextColor"; // 第二文本颜色

    private Resources mResources;
    private String mPackageName;
    private Context mContext;

    private static SkinManager instance;

    public static SkinManager getInstance(Context context) {
        if (null == instance) {
            instance = new SkinManager(context);
        }
        return instance;
    }

    public SkinManager(Context context) {
        mResources = context.getResources();
        mPackageName = context.getPackageName();
        mContext = context.getApplicationContext();
    }

    private String mStyleName = "";

    public void initTheme() {
        mStyleName = SkinSharedPreferences.getString(mContext);
    }

    public int getDialogSkinRes() {
        int themeIdentifier = mResources.getIdentifier("TVUITheme.TVUIDialogStyle" + mStyleName, "style", mPackageName);
        return themeIdentifier;
    }

    public int getSkinRes(String styleName) {
        setSkinName(styleName);
        return getSkinRes();
    }

    public int getSkinRes() {
        int themeIdentifier = mResources.getIdentifier("TVUITheme" + mStyleName, "style", mPackageName);
        return themeIdentifier;
    }

    public void setSkinName(String skinName) {
        mStyleName = skinName;
    }

    public String getSkinName() {
        return mStyleName;
    }

    /**
     * 主题名称
     * 比如 TVUITheme.Dark，继承 TVUITheme 的主题样式
     * @param ob
     * @param skinName
     */
    public void changeSkin(Object ob, String skinName) {
        changeSkin(ob, getSkinRes(skinName));
    }

    public void changeSkin(Object ob, String skinName, Resources resources) {
        changeSkin(ob, getSkinRes(skinName), resources);
    }

    public void changeSkin(Object ob, int skinRes) {
        changeSkin(ob, skinRes, null);
    }

    /**
     * 改变主题样式
     *     // 测试代码
     *    final SkinManager skinManager = new SkinManager(this);
     *    skinManager.addSkin(R.style.TestTVUITheme);
     *    skinManager.changeSkin(this, R.style.TestTVUITheme);
     */
    public void changeSkin(Object ob, int skinRes, Resources resources) {
        View view = null;
        if (null != ob) {
            if (ob instanceof Activity) { // 普通的 Activity支持
                Activity activity = (Activity) ob;
                Drawable drawable = getAttrDrawable(
                        activity, activity.getTheme(), R.attr.tvui_commonItem_detailColor);
                activity.getWindow().setBackgroundDrawable(drawable);
                // 获取 content view.
                view = activity.findViewById(android.R.id.content);
            } else if (ob instanceof Dialog) { // 系统设置5.0 - Dialog 主题切换支持
                Window window = ((Dialog) ob).getWindow();
                if (window != null) {
                    view = window.getDecorView();
                }
            } else if (ob instanceof View) {
                view = (View) ob;
            }
            mResources = resources != null ? resources : view.getResources();
            // 准备进行主题的切换
            if (null != view) {
                // 保存主题
                SkinSharedPreferences.putString(view.getContext(), mStyleName);
                // 主题切换
                SkinItem skinItem = new SkinItem(skinRes);
                // 获取主题 Theme
                Resources.Theme theme = skinItem.getTheme();
                // 设置主题
                setThemeDatas(view, skinRes, theme);
            }
        }
    }

    private void setThemeDatas(View view, int skinRes, Resources.Theme theme) {
        applyTheme(view, skinRes, theme);
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                setThemeDatas(viewGroup.getChildAt(i), skinRes, theme);
            }
        }
    }

    private void applyTheme(@NonNull View view, int skinRes, Resources.Theme theme) {
        try {
            theme.applyStyle(skinRes, true);
            // 拿到控件的 attr，放入. 现在是手动，如何自动？？？值得思考
                try {
//                    theme.applyStyle(skinRes, true);
                    Resources resources = mResources;
//                    view.getContext().setTheme(skinRes);
                    view.getContext().getTheme().setTo(theme);
                    if (view instanceof ISkinLayout) {
                        ISkinLayout skinLayout = (ISkinLayout) view;
                        SimpleArrayMap<String, Integer> skinAttrs = skinLayout.getSkinAttr();
                        // TODO：这里需要单独封装下，处理颜色等等替换逻辑.
                        for (int i = 0; i < skinAttrs.size(); i++) {
                            TypedValue value = new TypedValue();
                            String key = skinAttrs.keyAt(i); // background
                            Integer attr = skinAttrs.valueAt(i); // R.attr....
                            if (attr != null) {
                                if (BACKGROUND_TAG.equals(key)) {
                                    if (view instanceof TVUICommonItemView) {
                                        if (theme.resolveAttribute(attr, value, true)) {
                                            Drawable drawable = ResourcesCompat.getDrawable(resources, value.resourceId, theme);
                                            view.setBackgroundDrawable(drawable);
                                        }
                                    } else if (view instanceof TVUIButton) {
                                    } else {
                                        if (theme.resolveAttribute(attr, value, true)) {
                                            Drawable drawable = ResourcesCompat.getDrawable(resources, value.resourceId, theme);
                                            view.setBackgroundDrawable(drawable);
                                        }
                                    }
                                } else if (TEXT_COLOR_TAG.equals(key)) {
                                    if (view instanceof TVUICommonItemView) {
                                        TVUICommonItemView itemView = (TVUICommonItemView) view;
                                        ColorStateList color = getAttrColorStateList(view.getContext(), theme, attr);
                                        itemView.setTextColor(color);
                                    } else if (view instanceof TVUITextView) {
                                        TVUITextView textView = (TVUITextView) view;
                                        ColorStateList color = getAttrColorStateList(view.getContext(), theme, attr);
                                        textView.setTextColor(color);
                                    }
                                } else if (SECOND_TEXT_COLOR_TAG.equals(key)) {
                                    if (view instanceof TVUICommonItemView) {
                                        TVUICommonItemView itemView = (TVUICommonItemView) view;
                                        ColorStateList color = getAttrColorStateList(view.getContext(), theme, attr);
                                        itemView.setDetailTextColor(color);
                                    } else if (view instanceof TVUITextView) {
                                        TVUITextView textView = (TVUITextView) view;
                                        ColorStateList color = getAttrColorStateList(view.getContext(), theme, attr);
                                        textView.setTextColor(color);
                                    }
                                } else if (IMAGE_TINT_TAG.equals(key)) {
                                    if (view instanceof TVUICommonItemView) {
                                        TVUICommonItemView itemView = (TVUICommonItemView) view;
                                        ColorStateList color = getAttrColorStateList(view.getContext(), attr);
                                        itemView.setImageTintListAndMode(color, PorterDuff.Mode.SRC_IN);
                                    }
                                } else if (ARROW_TINT_TAG.equals(key)) {
                                    if (view instanceof TVUICommonItemView) {
                                        TVUICommonItemView itemView = (TVUICommonItemView) view;
                                        ColorStateList color = getAttrColorStateList(view.getContext(), attr);
                                        itemView.setArrowTintListAndMode(color, PorterDuff.Mode.SRC_IN);
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static TypedValue sTmpValue;

    public static ColorStateList getAttrColorStateList(Context context, int attrRes) {
        return getAttrColorStateList(context, context.getTheme(), attrRes);
    }

    public static ColorStateList getAttrColorStateList(Context context, Resources.Theme theme, int attr) {
        if (attr == 0) {
            return null;
        }
        if (sTmpValue == null) {
            sTmpValue = new TypedValue();
        }
        if (!theme.resolveAttribute(attr, sTmpValue, true)) {
            return null;
        }
        if (sTmpValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
                && sTmpValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
            return ColorStateList.valueOf(sTmpValue.data);
        }
        if (sTmpValue.type == TypedValue.TYPE_ATTRIBUTE) {
            return getAttrColorStateList(context, theme, sTmpValue.data);
        }
        if (sTmpValue.resourceId == 0) {
            return null;
        }
        return ContextCompat.getColorStateList(context, sTmpValue.resourceId);
    }

    public static Drawable getAttrDrawable(Context context, int attr) {
        return getAttrDrawable(context, context.getTheme(), attr);
    }

    public static Drawable getAttrDrawable(Context context, Resources.Theme theme, int attr) {
        if (attr == 0) {
            return null;
        }
        if (sTmpValue == null) {
            sTmpValue = new TypedValue();
        }
        if (!theme.resolveAttribute(attr, sTmpValue, true)) {
            return null;
        }
        if (sTmpValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
                && sTmpValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
            return new ColorDrawable(sTmpValue.data);
        }
        if (sTmpValue.type == TypedValue.TYPE_ATTRIBUTE) {
            return getAttrDrawable(context, theme, sTmpValue.data);
        }

        if (sTmpValue.resourceId != 0) {
            return getVectorDrawable(context, sTmpValue.resourceId);
        }
        return null;
    }

    public static Drawable getVectorDrawable(Context context, @DrawableRes int resVector) {
        try {
            return AppCompatResources.getDrawable(context, resVector);
        } catch (Exception e) {
            return null;
        }
    }

    public static int getAttrDimen(Context context, int attrRes) {
        if (sTmpValue == null) {
            sTmpValue = new TypedValue();
        }
        context.getTheme().resolveAttribute(attrRes, sTmpValue, true);
        return TypedValue.complexToDimensionPixelSize(sTmpValue.data, context.getResources().getDisplayMetrics());
    }

    public static float getAttrFloatValue(Context context, int attr) {
        return getAttrFloatValue(context.getTheme(), attr);
    }

    public static float getAttrFloatValue(Resources.Theme theme, int attr) {
        if (sTmpValue == null) {
            sTmpValue = new TypedValue();
        }
        theme.resolveAttribute(attr, sTmpValue, true);
        return sTmpValue.getFloat();
    }

    class SkinItem {
        private Resources.Theme theme;
        private int styleRes;

        public SkinItem(int res) {
            this.styleRes = res;
        }

        public int getStyleRes() {
            return styleRes;
        }

        public void setStyleRes(int styleRes) {
            this.styleRes = styleRes;
        }

        Resources.Theme getTheme() {
            if (theme == null) {
                theme = mResources.newTheme();
                theme.applyStyle(styleRes, true);
            }
            return theme;
        }

    }
}
/*

https://www.jianshu.com/p/61b79e7f88fc

【】obtainStyledAttributes函数获取属性
*obtainAttributes(AttributeSet set, int[] attrs) //从layout设置的属性集中获取attrs中的属性
*obtainStyledAttributes(int[] attrs) //从系统主题中获取attrs中的属性
*obtainStyledAttributes(int resId,int[] attrs) //从资源文件定义的style中读取属性
*obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)

attrs
attrs:int[],每个方法中都有的参数，就是告诉系统需要获取那些属性的值。

set
set：表示从layout文件中直接为这个View添加的属性的集合,如：android:layout_width="match_parent"。
注意，这里面的属性必然是通过xml配置添加的，也就是由LayoutInflater加载进来的布局或者View`才有这个属性集。

TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.yourAttr, typedValue, true);
// For string
typedValue.string
typedValue.coerceToString()
// For other data
typedValue.resourceId
typedValue.data;

 */